// wglmeshbuffer.cpp
//

#include "config.h"
#include "wgl/wglmeshbuffer.hpp"
#include "wgl/wglmesh.hpp"
#include "wgl/wgl_gl.hpp"

using namespace wgl;



// MeshBuffer::MeshBuffer
//
MeshBuffer::MeshBuffer ()
{
}



// MeshBuffer::~MeshBuffer
//
MeshBuffer::~MeshBuffer ()
{
}



// MeshBuffer::upload
//
void MeshBuffer::upload ( Mesh &mesh )
{
  polygon_type = mesh.get_polygon_type();
  
  gl.GenVertexArrays(1, &vao);
  gl.GenBuffers(1, &vbo);
  gl.GenBuffers(1, &ebo);

  gl.BindVertexArray(vao);

  gl.BindBuffer(GL_ARRAY_BUFFER, vbo);
  gl.BufferData(GL_ARRAY_BUFFER,
                sizeof(Vertex) * mesh.n_vertices(),
                mesh.vertices_data(),
                GL_STATIC_DRAW);

  // pos
  gl.VertexAttribPointer(0,
                         3,
                         GL_FLOAT,
                         GL_FALSE,
                         sizeof(Vertex),
                         (void *) 0);
  gl.EnableVertexAttribArray(0);

  // col
  gl.VertexAttribPointer(1,
                         3,
                         GL_FLOAT,
                         GL_FALSE,
                         sizeof(Vertex),
                         (void *) offsetof(Vertex, col));
  gl.EnableVertexAttribArray(1);

  // normal
  gl.VertexAttribPointer(2,
                         3,
                         GL_FLOAT,
                         GL_FALSE,
                         sizeof(Vertex),
                         (void *) offsetof(Vertex, norm));
  gl.EnableVertexAttribArray(2);

  // uv
  gl.VertexAttribPointer(3,
                         2,
                         GL_FLOAT,
                         GL_FALSE,
                         sizeof(Vertex),
                         (void *) offsetof(Vertex, uv));
  gl.EnableVertexAttribArray(3);
  
  // ebo - NOTE: don't unbind this one (unbind would be recorded by the vao)
  n_indices = mesh.n_indices();
  gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
  gl.BufferData(GL_ELEMENT_ARRAY_BUFFER,
                sizeof(GLuint) * n_indices,
                mesh.indices_data(),
                GL_STATIC_DRAW);
  
  // You can unbind the VAO afterwards so other VAO calls won't
  // accidentally modify this VAO, but this rarely
  // happens. Modifying other VAOs requires a call to
  // glBindVertexArray anyways so we generally don't unbind VAOs
  // (nor VBOs) when it's not directly necessary.
  gl.BindVertexArray(0);
}



void MeshBuffer::render ()
{
  gl.BindVertexArray(vao);
  gl.DrawElements(polygon_type, n_indices, GL_UNSIGNED_INT, (void *) 0);
}
